﻿using System;
using System.Collections.Generic;
using TA.JSON;
using System.Text;
using System.IO;
using System.Web.UI;
using System.ComponentModel;

namespace TA.Turbo.Controls
{
	/// <summary>
	/// Base class for defining a property that exists both on client and server.
	/// </summary>
	public abstract class BasePropertyDefinition
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="shortName"></param>
		public BasePropertyDefinition(string name, string shortName)
		{
			this._name = name;
			this._shortName = shortName;

			this.IsUsedByClient = true;
		}
		#endregion
		#region EVENTS
		#endregion
		#region PROPS
		/// <summary>
		/// The name of the property.
		/// </summary>
		public string Name { get { return _name; } }
		/// <summary>
		/// The short name of the property, used for JSON client-server communications.
		/// </summary>
		public string ShortName { get { return _shortName; } }
		/// <summary>
		/// True if this property is sent to the client as part of HTML.
		/// </summary>
		/// <remarks>
		/// If this property is set to true, then the value of this property will not be JSON serialized.
		/// </remarks>
		public bool IsHTML { get; set; }
		/// <summary>
		/// True if this property is used by the client-side script.
		/// </summary>
		/// <remarks>
		/// This property will be JSON serialized even if this property is false if the control requires it.
		/// </remarks>
		public bool IsUsedByClient { get; set; }
		/// <summary>
		/// Custom Deserializer to be called during LoadState.
		/// </summary>
		public Action<TControl, JsonReader> Deserializer { get; set; }
		/// <summary>
		/// Custom Serializer to be called during SaveState.
		/// </summary>
		public Action<TControl, JsonWriter> Serializer { get; set; }
		#endregion
		#region METHODS
		/// <summary>
		/// Serializes the value of this property to the specified <see cref="JsonWriter"/>, if the conditions are right.
		/// </summary>
		/// <remarks>
		/// This will serialize the property if initialRender
		/// is false or the value of the property is not equal to the default value 
		/// and if the property is not a HTML-bound property (for ex., CssClass).
		/// </remarks>
		/// <param name="control"></param>
		/// <param name="jw"></param>
		/// <param name="initialRender"></param>
		/// <returns>True if property was serialized, otherwise false.</returns>
		public virtual bool SerializeValue(TControl control, JsonWriter jw, bool initialRender)
		{
			if (
					initialRender // rendering the page 
					&&
					(
						(this.IsHTML && control.TPage.JavaScript == true) // not outputting HTML-bound properties (class, style, etc.) if JS is available
						||
						(!this.IsUsedByClient && !control.SerializedPropertiesList.Contains(this.Name))
						||
						this.ValueIsDefault(control) // not outputting the default values
					)
				)
			{
			}
			else
			{
				jw.PropertyName(this.ShortName);
				this.DoSerializeValue(control, jw);
				return true;
			}
			return false;
		}
		/// <summary>
		/// When implemented, deserializes the value of this property from the specified <see cref="JsonReader"/>.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="jr"></param>
		public abstract void DeserializeValue(TControl control, JsonReader jr);
		#endregion
		#endregion
		#region INTERNAL
		#region CONST/STATIC
		#endregion
		#region VARS
		string _name, _shortName;
		#endregion
		#region PROPS
		#endregion
		#region METHODS
		/// <summary>
		/// When implemented, returns true if the value of this property for the specified control is equal to the default, otherwise false.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		protected abstract bool ValueIsDefault(TControl control);
		/// <summary>
		/// When implemented, serializes the value of this property for the specified control to the specified <see cref="JsonWriter"/>.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="jw"></param>
		protected abstract void DoSerializeValue(TControl control, JsonWriter jw);
		#endregion
		#endregion
	}
	/// <summary>
	/// Collection of property defitions for a control.
	/// </summary>
	public class Properties : Dictionary<string, BasePropertyDefinition>
	{
	}
}
